"""


"""

import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
sys.path.append("..")

from common.qt_worker import Worker
from common import utils
from drivers.driver_serial import *

from ui.Ui_humiture_sensor_dialog import Ui_HumitureSensorDialog

class HumitureSensorDialog(QDialog):
    
    BUFFER_SIZE = 1024
    
    def __init__(self, parent = None):
        super().__init__(parent)
        self.ui = Ui_HumitureSensorDialog()
        self.ui.setupUi(self)
        
        self.devices = []
        self.current_serial_device : SerialDevice = None
        self.refresh_worker: Worker = None
        self.receive_worker: Worker = None
        
        self.init_ui()
        
        self.ui.edit_device_addr.setText("0x01")
        self.ui.cb_reg_addr.addItem("0x03 0x00")
        self.ui.cb_reg_addr.addItem("0x00 0x02")
        self.ui.sb_reg_count.setValue(2)
        
    @pyqtSlot()
    def on_btn_connect_clicked(self):
        if self.current_serial_device is not None:
            self.current_serial_device.close()
            self.current_serial_device = None
            self.ui.btn_connect.setText("连接设备")
            self.ui.label_state.setPixmap(QPixmap(":/icon/disc"))
            return
        
        index = self.ui.cb_devices.currentIndex()
        if index == -1:
            QMessageBox.warning(self, "警告", "请先扫描并选择设备")
            return
        port, description = self.devices[index]
        baudrate = self.ui.cb_baudrate.currentText()
        print("connect: ", self.devices[index], baudrate)
        
        # PARITY_NONE, PARITY_EVEN, PARITY_ODD
        self.current_serial_device = SerialDevice(
                    port=port, baud_rate=baudrate, timeout=None, 
                     bytesize = 8, stopbits = 1, parity = 'N')
        rst, msg = self.current_serial_device.open()
        if not rst:
            QMessageBox.warning(self, "连接失败", msg)
            return
        
        self.ui.btn_connect.setText("断开连接")
        self.ui.label_state.setPixmap(QPixmap(":/icon/conn"))
        # 开启循环接收任务
        self.receive_worker = Worker(self.receive_data_loop)
        self.receive_worker.signal_connect(
            msg_handler=self.on_receive_data
        )
        self.receive_worker.start()
        
    def show_log(self, log, is_send = True):
        
        if is_send:
            full_log = f"发→◇{log}"
        else:
            full_log = f"收→◆{log}"
        
        print(full_log)
        self.ui.edit_console.appendPlainText(full_log)
        # 将self.ui.edit_console移动到末尾
        self.ui.edit_console.moveCursor(QTextCursor.End)
        
    @pyqtSlot(object)
    def on_receive_data(self, data):
        """子线程收到数据
        """
        
        text = ""
        if len(data) > 3 and data[0] == 0x01 and data[1] == 0x03:
            if data[2] == 0x14: # 10 名称
                # 将data[3:13] 转成字符串
                name = utils.decode_data(bytes(data[3:13]))
                text = f"名称: {name}"
            elif data[2] == 0x04:
                # 将3,4取出来, 转成10进制, x0.1作为温度
                temperature = (data[3] << 8) + data[4]
                temperature = temperature / 10.0
                
                # 将5,6取出来, 转成10进制, x0.1作为湿度
                humidity = (data[5] << 8) + data[6]
                humidity = humidity / 10.0
                
                text = f"温度: {temperature:.1f}℃, 湿度: {humidity:.1f}%"
            else:
                text = f"未解析数据类型"
        else:
            text = f"未知数据"
            
        self.show_log(f"{utils.hex2str(data, with_0x=False)}\t=>{text}", is_send=False)
        
    def receive_data_loop(self, worker: Worker):
        while worker.is_running:
            waiting_count = self.current_serial_device.serial.in_waiting
            if waiting_count > 0:
                data = self.current_serial_device.read(waiting_count)
                worker.emit_msg(data)
            time.sleep(0.1)
            
        print("receive_data_loop exit!")
        
    @pyqtSlot()
    def on_btn_refresh_clicked(self):
        if self.refresh_worker is not None and self.refresh_worker.is_running:
            return 
            
        self.refresh_worker = Worker(scan_serial_ports)
        self.refresh_worker.signal_connect(
            result_handler=self.on_refresh_serial_port_result
        )
        self.refresh_worker.start()
        
        
    @pyqtSlot(object)
    def on_refresh_serial_port_result(self, devices):
        self.ui.cb_devices.clear()
        self.devices = devices
        for port, description in devices:
            self.ui.cb_devices.addItem(description)
        
    @pyqtSlot()
    def on_read_humiture(self):
        # 确认已连接串口设备
        if self.current_serial_device is None:
            QMessageBox.warning(self, "警告", "请先连接设备")
            return
        
        # 给串口发消息
        bytes_data = b"\x01\x03\x03\x00\x00\x02\xC4\x4F"
        self.current_serial_device.write(bytes_data)
        
        self.show_log(utils.hex2str(bytes_data, with_0x=False))
        
    
    @pyqtSlot()
    def on_btn_read_clicked(self):
        """构建读设备寄存器的命令
        地址码 + 功能码 + 寄存器地址 + 寄存器个数 + CRC低位 + CRC高位
           1      1          2          2           1        1
        
        功能码 0x03读取  0x16写入
        """
        if self.current_serial_device is None:
            QMessageBox.warning(self, "警告", "请先连接设备")
            return
        
        device_addr = self.ui.edit_device_addr.text()
        reg_addr = self.ui.cb_reg_addr.currentText()
        reg_count = self.ui.sb_reg_count.value()

        req_data = bytearray()
        # 添加设备地址
        req_data.append(int(device_addr, 16))
        # 添加功能码
        req_data.append(0x03)
        # 将寄存器地址转成两个字节
        red_addr_hex: bytes = utils.str2hex(reg_addr)
        req_data.extend(red_addr_hex)
        # 将reg_count转成两个字节
        req_data.extend(reg_count.to_bytes(2, byteorder='big'))
        # 计算crc16
        crc = utils.crc16_modbus(req_data)
        req_data.extend(crc.to_bytes(2, byteorder='little'))
        
        # 将req_data转成bytes
        self.current_serial_device.write( bytes(req_data))
        # 打印req_data
        self.show_log(utils.hex2str(req_data, with_0x=False))        
        
        
    
    def init_ui(self):
        self.ui.btn_read_humiture.clicked.connect(self.on_read_humiture)
    
if __name__ == '__main__':
    app = QApplication(sys.argv)

    w = HumitureSensorDialog()
    w.show()
    
    sys.exit(app.exec_())